-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic macOS support #3
Conversation
} | ||
|
||
/// PreviewSnapshots assertion using `named` parameter | ||
func test_namedAssertion() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was just added in the last PR, but this test felt redundant now that every test is using the named
argument
Thanks for making this. |
@andrewtheis The main You could try including this strategy in your project. extension Snapshotting where Value: SwiftUI.View, Format == NSImage {
static var image: Self {
Snapshotting<NSView, NSImage>.image(size: .init(width: 400, height: 400)).pullback { view in
let view = NSHostingView(rootView: view)
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor
return view
}
}
} |
@jflan-dd makes sense. This is code I used, which also correctly scales the image based on the backing scale factor - necessary if you're using Xcode Cloud, which runs at a 1px = 1pt resolution. Hope this helps anyone else that stumbles upon this! #if os(macOS)
import AppKit
import Cocoa
extension Snapshotting where Value == NSView, Format == NSImage {
public static func scaleFactorAdjustedImage(
precision: Float = 1,
perceptualPrecision: Float = 1,
size: CGSize
) -> Snapshotting {
return SimplySnapshotting.image(
precision: precision, perceptualPrecision: perceptualPrecision
).asyncPullback { view in
Async { callback in
view.frame.size = size
guard view.frame.width > 0, view.frame.height > 0 else {
fatalError("View not renderable to image at size \(view.frame.size)")
}
let bitmapRep = view.bitmapImageRepForCachingDisplay(in: view.bounds)!
view.cacheDisplay(in: view.bounds, to: bitmapRep)
// Use the scaling function to get the scaled image
let image = adjustForBackingScaleFactor(bitmapRep, in: view)
callback(image)
}
}
}
// Function to scale the image based on the window's scale factor
static func adjustForBackingScaleFactor(_ bitmapRep: NSBitmapImageRep, in view: NSView) -> NSImage {
let scaleFactor = 1 / (NSScreen.main?.backingScaleFactor ?? view.window?.backingScaleFactor ?? 1)
let scaledSize = NSSize(width: bitmapRep.size.width * scaleFactor, height: bitmapRep.size.height * scaleFactor)
guard scaleFactor < 1, let scaledBitmapRep = bitmapRep.copy() as? NSBitmapImageRep else {
return NSImage(size: bitmapRep.size, flipped: false) { rect in
bitmapRep.draw(in: rect)
}
}
scaledBitmapRep.size = scaledSize
return NSImage(size: scaledSize, flipped: false) { rect in
scaledBitmapRep.draw(in: rect)
}
}
}
#endif You'll need some additional code to wrap it in a NSHostingController and get the sizeThatFits |
@andrewtheis Thanks for sharing this! |
Add macOS support to
Package.swift
and loosen hardUIImage
requirement to allow any snapshotting strategy that takesAnyView
/ModifiedView
as input.